﻿/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "imagescaling.h"
#include "math.h"
#include "jconcurrentmap.h"

#ifndef QT_NO_CONCURRENT

const int imageSize = 100;

QImage scale(const QString &imageFileName)
{
    QImage image(imageFileName);
    return image.scaled(QSize(imageSize, imageSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}

Images::Images(QWidget *parent) 
: QWidget(parent)
{
    setWindowTitle(tr("Image loading and scaling example"));
    resize(800, 600);

    openButton = new QPushButton(tr("Open Images"));
    connect(openButton, SIGNAL(clicked()), SLOT(open()));

    cancelButton = new QPushButton(tr("Cancel"));
    cancelButton->setEnabled(false);
    connect(cancelButton, SIGNAL(clicked()), this, SLOT(onCancelClicked()));
   
    pauseButton = new QPushButton(tr("Pause/Resume"));
    pauseButton->setEnabled(false);
    connect(pauseButton, SIGNAL(clicked()), this, SLOT(onPauseClicked()));
   
    QHBoxLayout *buttonLayout = new QHBoxLayout();
    buttonLayout->addWidget(openButton);
    buttonLayout->addWidget(cancelButton);
    buttonLayout->addWidget(pauseButton);
    buttonLayout->addStretch();

    imagesLayout = new QGridLayout();

    mainLayout = new QVBoxLayout();
    mainLayout->addLayout(buttonLayout);
    mainLayout->addLayout(imagesLayout);
    mainLayout->addStretch();
    setLayout(mainLayout);

    imageScaling.setObserver(this);
}

Images::~Images()
{
    imageScaling.cancel();
    imageScaling.waitForFinished();
}

void Images::open()
{
    // Cancel and wait if we are already loading images.
    if (imageScaling.isRunning()) {
        imageScaling.cancel();
        imageScaling.waitForFinished();
    }

    // Show a file open dialog at QDesktopServices::PicturesLocation.
    QStringList files = QFileDialog::getOpenFileNames(this, tr("Select Images"), 
                            QDesktopServices::storageLocation(QDesktopServices::PicturesLocation),
                            "*.jpg *.png");

    if (files.count() == 0)
        return;

    // Do a simple layout.
    qDeleteAll(labels);
    labels.clear();

    int dim = sqrt(qreal(files.count())) + 1;
    for (int i = 0; i < dim; ++i) {
        for (int j = 0; j < dim; ++j) {
            QLabel *imageLabel = new QLabel;
            imageLabel->setFixedSize(imageSize,imageSize);
            imagesLayout->addWidget(imageLabel,i,j);
            labels.push_back(imageLabel);
        }
    }

    // Use mapped to run the thread safe scale function on the files.
    imageScaling.setFuture(JConcurrent::mapped(files, scale));
    //imageScaling2.setFuture(JConcurrent::map(files, scale));

    openButton->setEnabled(false);
    cancelButton->setEnabled(true);
    pauseButton->setEnabled(true);
}

void Images::onCancelClicked()
{
    imageScaling.cancel();
}

void Images::onPauseClicked()
{
    imageScaling.togglePaused();
}

void Images::started()
{
    qDebug() << "task started";
}

void Images::finished()
{
    qDebug() << "task finshed";
    openButton->setEnabled(true);
    cancelButton->setEnabled(false);
    pauseButton->setEnabled(false);
}

void Images::canceled()
{
    qDebug() << "task canceled";
    imageScaling.cancel();
}

void Images::paused()
{
    qDebug() << "task paused";
}

void Images::resumed()
{
    qDebug() << "task resumed";
}

void Images::resultReadyAt(int resultIndex)
{
    J_UNUSED(resultIndex);
    qDebug() << "resultReadyAt task";
    labels[resultIndex]->setPixmap(QPixmap::fromImage(imageScaling.resultAt(resultIndex)));
}

void Images::resultsReadyAt(int beginIndex, int endIndex)
{
    J_UNUSED(beginIndex);
    J_UNUSED(endIndex);
    qDebug() << "resultsReadyAt task";
}

void Images::progressRangeChanged(int minimum, int maximum)
{
    J_UNUSED(minimum);
    J_UNUSED(maximum);
    qDebug() << "progressRangeChanged task";
}

void Images::progressValueChanged(int progressValue)
{
    J_UNUSED(progressValue);
    qDebug() << "progressValueChanged task";
}

void Images::progressTextChanged(const std::string &progressText)
{
    J_UNUSED(progressText);
    qDebug() << "progressTextChanged task";
}

#endif // QT_NO_CONCURRENT

